/*************************************************************************
Function builds an hash array, collision resolution, insert, delete,
search, and efficiency
	Written By: Lam Lu
	Date: May/30/10
*************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "lamHash.h"
#include <crtdbg.h>

#define MAX_STR 200
#define ARR_SIZE 71//number of elements 34


FILE* readFile(void);
void storeData(FILE* infile);
void processData(FILE* infile, HASH* pHash, int numElems);
char* allocateString(const char* string);

void printHash(HASH* pHash);
void getString(char* string);
SOLDIER* getData(void);

int main (void)
{

	//Local Declarations
	FILE* infile;
	HASH* pHash;
	int numElems = 4;
	char decide[MAX_STR] = {'\0'};
	char string[MAX_STR];
	
	int targetIndex;
	int deleteIndex;
	double loadFactor;
	int collisionCount;
	int longestCol;
	SOLDIER* soldier;
	
	SOLDIER* dataOut;
	

	//Statements
	infile = readFile();
	pHash = buildHash(ARR_SIZE); //changing buildHash, dont need to pass the array inside the buildHash
	if(!pHash){printf("Allocation failed!!\n"); exit(101);}
	processData(infile, pHash, numElems);
	decide[0] = 'c';
	while(decide[0] == 'c')
	{
		printHash(pHash);
		printf("Search: ");
		getString(string);		
		if(!searchHash(pHash, string, &targetIndex, ARR_SIZE))
			printf("Search Not Found!\n\n");
		else printf("Target found at: %d\n\n", targetIndex);
		printf("Delete: ");
		getString(string);
		if(!deleteHash(pHash, string, &deleteIndex, &dataOut, ARR_SIZE))
			printf("delete not found!\n\n");
		else
		{
			printf("deleted target at : %d\n\n", deleteIndex);
			free(dataOut->division);
			free(dataOut->jobCat);
			free(dataOut->name);
			free(dataOut->rank);
			free(dataOut);
		}
		
		printf("\nInserting data ");	
		soldier = getData();
		if(!insertHash(pHash, soldier->name, soldier, ARR_SIZE)){printf("Array size is not enough! Quitting program!\n"); system("pause"), exit(101);}
		getEfficiency(pHash, &loadFactor, &collisionCount, &longestCol, ARR_SIZE);
		printf("\nLoad Factor: %4.2f%%", loadFactor);
		printf("\n%d data records have collisions", collisionCount);
		printf("\nLongest collision Path: %d", longestCol);
		printf("\ndecide: ");
		getString(decide);

	}	
	destroyHash(pHash, ARR_SIZE, freeMemory);
	printf(_CrtDumpMemoryLeaks()? "Memory Leak\n" : "No Leak\n");
	system("pause");

	
}//end main


void getString(char* string)
{
	fscanf(stdin, " %[^\n]", string);
}
/*************************************************************************
The function reads input file  
	Pre: file pointer
	Post: none
	Return: pointer to file
*************************************************************************/
FILE* readFile(void)
{
   // Declarations
   char filename[MAX_STR];
   FILE* infile;
   // Statements
   do
   {
	   printf("Enter file name : ");
	   fgets(filename, MAX_STR, stdin);
	   filename[strlen(filename) - 1] = '\0';
	   infile = fopen(filename, "r");
	   if(!infile)
	   printf("Error reading file!!!\n\n");
   }
   while(!infile);
   return infile;
}// readFile 


/*************************************************************************
The function processes data from a input file
	Pre: infile, pHash
	Post: data processed
	Return: none
	Preconditions: infile and pHash have been opened/created
*************************************************************************/
void processData(FILE* infile, HASH* pHash, int numElems)
{
	//Local Declarations
	SOLDIER* soldier;
	char name[MAX_STR] ={'\0'};
	int  exp;
    char rank[MAX_STR];
    char division[MAX_STR];
    char job[MAX_STR];

	//Statements
	rewind(infile);
	while((fscanf(infile, " %[^,], %d, %[^,], %[^,], %[^\n]", name, &exp, rank, division, job)!= EOF))	   
	{
		
		if(!(soldier = (SOLDIER*) malloc(sizeof (SOLDIER)))){printf("\n Allocation failed ! "); exit(101);}
		soldier->name = allocateString(name);
		soldier->experience =  exp;
		soldier->rank = allocateString(rank);
		soldier->division = allocateString(division);
		soldier->jobCat = allocateString(job);
		if(!insertHash(pHash, name, soldier, ARR_SIZE)){printf("Array size is not enough! Quitting program!\n"); system("pause"), exit(101);}
	}
	fclose(infile);
}//end processData

SOLDIER* getData(void)
{
	SOLDIER* soldier;
	char name[MAX_STR] ={'\0'};
	char exp[MAX_STR];
    char rank[MAX_STR];
    char division[MAX_STR];
    char job[MAX_STR];
	if(!(soldier = (SOLDIER*) malloc(sizeof (SOLDIER)))){printf("\n Allocation failed ! "); exit(101);}
	else
	{
		printf("\nEnter name: ");
		getString(name);
		soldier->name = allocateString(name);
		printf("\nEnter exp: ");
		getString(exp);
		sscanf(exp, "%d", &soldier->experience);
		printf("\nEnter rank: ");
		getString(rank);
		soldier->rank = allocateString(rank);
		printf("\nEnter job: ");
		getString(job);
		soldier->jobCat = allocateString(job);
		printf("\nEnter division: ");
		getString(division);
		soldier->division = allocateString(division);
	}
		return soldier;
}

/**************************************************************************
The function allocates a string with the exact size and return the pointer
to string allocated
	Pre: string 
	Post: memory allocated
	Return: pointer to string allocated
	Preconditions: string is not empty
**************************************************************************/
char* allocateString(const char* string)
{
	//Local Declarations
	char *pc;
	//Statements
	pc = (char*) malloc(strlen(string)+1);
	if(!pc)
	{
		printf("\n Allocation failed!\n");
		exit(101);
	}
	strcpy(pc, string);
	return pc;
}
 




/**************************
print hash
**************************/
void printHash(HASH* pHash)
{
	HASH* pWalker, *pEnd;
	int i;

	pEnd = pHash + ARR_SIZE;
	for(i = 0, pWalker = pHash; pWalker < pEnd; pWalker++, i++)
	{
		
		if(pWalker->pSoldier != NULL)
		{
			printf("at index %2d: %-20s  exp: %-5d probe: %-2d\n"
				   //"             %-20s\n"
				   //"             %-20s\n"
				   /*"             %-20s\n"*/,i, pWalker->pSoldier->name, pWalker->pSoldier->experience, pWalker->probe//, pWalker->pSoldier->rank, 
				/*pWalker->pSoldier->division, pWalker->pSoldier->jobCat*/);
		}
	}
}
